#ifndef FLASH_H
#define FLASH_H

#include <stdint.h>
#include "main.h"

/* sector size */
#define SIZE_16KB           ((uint32_t)0x00004000U)        /*!< size of 16KB*/
#define SIZE_64KB           ((uint32_t)0x00010000U)        /*!< size of 64KB*/
#define SIZE_128KB          ((uint32_t)0x00020000U)        /*!< size of 128KB*/
#define SIZE_256KB          ((uint32_t)0x00040000U)        /*!< size of 256KB*/

#define FLASH_PAGE_SIZE     ((uint16_t)0x1000U)	/* bank0 2kB each page */

/* FMC BANK address */
#define FLASH_START_ADDRESS          FLASH_BASE                               /*!< FMC start address */
#define FLASH_BANK0_START_ADDRESS    FLASH_START_ADDRESS                      /*!< FMC BANK0 start address */
#define FLASH_BANK1_START_ADDRESS    ((uint32_t)0x08100000U)                  /*!< FMC BANK1 start address */
#define FLASH_SIZE                   (*(uint16_t *)0x1FFF7A22U)               /*!< FMC SIZE */
#define FLASH_END_ADDRESS            (FLASH_BASE + (FLASH_SIZE * 1024) - 1)   /*!< FMC end address */
#define FLASH_MAX_END_ADDRESS        ((uint32_t)0x08300000U)                  /*!< FMC maximum end address */

/* FMC error message */
#define FLASH_WRONG_SECTOR_NAME      ((uint32_t)0xFFFFFFFFU)        /*!< wrong sector name*/
#define FLASH_WRONG_SECTOR_NUM       ((uint32_t)0xFFFFFFFFU)        /*!< wrong sector number*/
#define FLASH_INVALID_SIZE           ((uint32_t)0xFFFFFFFFU)        /*!< invalid sector size*/
#define FLASH_INVALID_ADDR           ((uint32_t)0xFFFFFFFFU)        /*!< invalid sector address*/

#define FLASH_ERASE_ADDR_BASE 0x08004000
#define FLASH_ERASE_BYTES ((512 - 16) * KB)

#define ACTIVE_APP_ADDR_BASE 0x08008000
#define ACTIVE_APP_MAX_BYTES (224 * KB)

#define FACTORY_APP_ADDR_BASE 0x08040000
#define FACTORY_APP_MAX_BYTES (256 * KB)

#define APP_MAX_BYTES Min(ACTIVE_APP_MAX_BYTES, FACTORY_APP_MAX_BYTES)

/**
 * @brief Flash数据存储空间分配
 */
#define USER_ADDRESS_START               FLASH_ERASE_ADDR_BASE
#define USER_DATA_ADDR_BASE              (0x08004000 + 0*FLASH_PAGE_SIZE)/*4KB,0x08004000,用户参数存储首地址*/
#define DOWNLOAD_DATA_ADDR_BASE          (0x08004000 + 1*FLASH_PAGE_SIZE)/*4KB,0x08005000,下载程序标志存储首地址，切勿对其操作*/
#define PWMI_CALIBRATION_DATA_ADDR_BASE  (0x08004000 + 2*FLASH_PAGE_SIZE)/*4KB,0x08006000,PWMI标定参数存储首地址*/
                                                                         /*4KB,0x08007000,未分配空间地址 */
#define USER_ADDRESS_END                 ACTIVE_APP_ADDR_BASE


/* FMC sector information */
typedef struct
{
    uint32_t sector_name;                                         /*!< the name of the sector */
    uint32_t sector_num;                                          /*!< the number of the sector */
    uint32_t sector_size;                                         /*!< the size of the sector */
    uint32_t sector_start_addr;                                   /*!< the start address of the sector */
    uint32_t sector_end_addr;                                     /*!< the end address of the sector */
} flash_sector_info_struct;

extern int Flash_write_32bit_data_with_sector_erased(uint32_t address, uint16_t length, const uint32_t *data_32);
extern int Flash_erase_sectors_by_start_address_length(uint32_t address, uint32_t length);
extern void Flash_erase_sector_by_address(uint32_t address);
extern void Flash_write_32bit_data(uint32_t address, uint16_t length, int32_t *data_32);
/**
 * @brief 擦除一页数据
 * [param in] address:擦除页的首地址
 */
extern void Flash_erase_page(uint32_t address);
/*!
    \brief      写16位数据
    \param[in]  address: 页首地址
    \param[in]  length: 数据长度
    \param[in]  data: 数据指针
    \param[out] none
    \retval     0: write succeed;-1: write failed     
*/
extern int Flash_write_16bit_data_with_page_erased(uint32_t address, uint16_t length, const uint16_t *data);
/*!
    \brief      读8位数据
    \param[in]  address: 页首地址
    \param[in]  length: 数据长度
    \param[in]  data: 数据指针
    \param[out] none      
*/
extern void Flash_read_8bit_data(uint32_t address, uint16_t length, uint8_t *data);
/*!
    \brief      读16位数据
    \param[in]  address: 页首地址
    \param[in]  length: 数据长度
    \param[in]  data_16: 数据指针
    \param[out] none      
*/
extern void Flash_read_16bit_data(uint32_t address, uint16_t length, uint16_t *data_16);
/*!
    \brief      读32位数据
    \param[in]  address: 地址
    \param[in]  length: 数据长度
    \param[in]  data_32: 数据指针
    \param[out] none
    \retval     none
*/
extern void Flash_read_32bit_data(uint32_t address, uint16_t length, int32_t *data_32);

#endif
